﻿using Catalogo.Portable.DataSources;
using Catalogo.Portable.Model;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Catalogo.SetupAzureMobileService
{
    class Program
    {
        const string STORAGE_ACCOUNT_NAME = "[sua conta]";
        const string STORAGE_ACCOUNT_KEY = "[sua chave]";
        const string STORAGE_CONTAINER = "catalogo";
        const string CaminhoImagensCategorias = @"Data\Imagens\Categorias\";
        const string CaminhoImagensItens = @"Data\Imagens\Itens\";
        const string CaminhoImagensEmpresa = @"Data\Imagens\Empresa\";

        static void Main(string[] args)
        {
            //ExportarDadosAsync();
            ImportarDadosAsync();
            Console.ReadLine();
        }

        private static async Task ImportarDadosAsync()
        {
            Console.WriteLine("Importando dados...");
            try
            {
                var storageAccount = new CloudStorageAccount(new StorageCredentials(STORAGE_ACCOUNT_NAME, STORAGE_ACCOUNT_KEY), true);
                var blobStorage = storageAccount.CreateCloudBlobClient();
                var container = blobStorage.GetContainerReference(STORAGE_CONTAINER);
                container.CreateIfNotExists();
                container.SetPermissions(new BlobContainerPermissions() { PublicAccess = BlobContainerPublicAccessType.Blob });

                Console.WriteLine("Importando categorias...");
                var categoriasComItensExistentes = await CatalogoDataSource.Instance.ObterCategoriasComItensAsync();

                var categoriasSerializer = new DataContractSerializer(typeof(List<Categoria>));
                List<Categoria> categoriasArquivo;
                using (var fileStream = File.OpenRead(@"Data\categorias.xml"))
                {
                    categoriasArquivo = categoriasSerializer.ReadObject(fileStream) as List<Categoria>;
                }

                var itensSerializer = new DataContractSerializer(typeof(List<Item>));
                List<Item> itensArquivo;
                using (var fileStream = File.OpenRead(@"Data\itens.xml"))
                {
                    itensArquivo = itensSerializer.ReadObject(fileStream) as List<Item>;
                }

                foreach (var categoriaArquivo in categoriasArquivo)
                {
                    var categoriaExistente = categoriasComItensExistentes.FirstOrDefault((c) => c.Nome == categoriaArquivo.Nome);
                    var idCategoriaArquivo = categoriaArquivo.Id;
                    string idCategoriaExistente;
                    if (categoriaExistente == null)
                    {
                        categoriaArquivo.ImageUrl = UploadBlob(container, "categorias", CaminhoImagensCategorias, categoriaArquivo.ImageUrl);
                        categoriaArquivo.Id = null;
                        await CatalogoDataSource.Instance.InserirCategoriaAsync(categoriaArquivo);
                        idCategoriaExistente = categoriaArquivo.Id;
                        categoriaExistente = categoriaArquivo;
                    }
                    else
                    {
                        idCategoriaExistente = categoriaExistente.Id;
                    }

                    foreach (var itemArquivo in itensArquivo.Where((i) => i.IdCategoria == idCategoriaArquivo))
                    {
                        if (categoriaExistente.Itens == null || !categoriaExistente.Itens.Any((i) => i.Nome == itemArquivo.Nome))
                        {
                            itemArquivo.ImageUrl = UploadBlob(container, "itens", CaminhoImagensItens, itemArquivo.ImageUrl);
                            itemArquivo.Id = null;
                            itemArquivo.IdCategoria = idCategoriaExistente;
                            await CatalogoDataSource.Instance.InserirItemAsync(itemArquivo);
                        }
                    }
                }
                Console.WriteLine("Categorias importadas.");

                Console.WriteLine("Importando empresa...");
                var empresaExistente = await CatalogoDataSource.Instance.ObterEmpresaAsync();
                if (empresaExistente == null)
                {
                    var empresaSerializer = new DataContractSerializer(typeof(Empresa));
                    Empresa empresaArquivo;
                    using (var fileStream = File.OpenRead(@"Data\empresa.xml"))
                    {
                        empresaArquivo = empresaSerializer.ReadObject(fileStream) as Empresa;
                    }
                    empresaArquivo.ImageUrl = UploadBlob(container, "empresa", CaminhoImagensEmpresa, empresaArquivo.ImageUrl);
                    empresaArquivo.LiveTileBig1 = UploadBlob(container, "empresa", CaminhoImagensEmpresa, empresaArquivo.LiveTileBig1);
                    empresaArquivo.LiveTileBig2 = UploadBlob(container, "empresa", CaminhoImagensEmpresa, empresaArquivo.LiveTileBig2);
                    empresaArquivo.LiveTileSmall1 = UploadBlob(container, "empresa", CaminhoImagensEmpresa, empresaArquivo.LiveTileSmall1);
                    empresaArquivo.LiveTileSmall2 = UploadBlob(container, "empresa", CaminhoImagensEmpresa, empresaArquivo.LiveTileSmall2);
                    empresaArquivo.Id = null;
                    await CatalogoDataSource.Instance.InserirEmpresaAsync(empresaArquivo);
                    Console.WriteLine("Empresa importada.");
                }
            }
            catch (Exception e)
            {
                Console.Write("Erro: ");
                Console.WriteLine(e.ToString());
            }
        }

        private static async Task ExportarDadosAsync()
        {
            Console.WriteLine("Exportando dados...");
            try
            {
                var webClient = new WebClient();
                Directory.CreateDirectory(CaminhoImagensCategorias);
                Directory.CreateDirectory(CaminhoImagensItens);
                Directory.CreateDirectory(CaminhoImagensEmpresa);

                Console.WriteLine("Exportando categorias...");
                var categoriasComItens = await CatalogoDataSource.Instance.ObterCategoriasComItensAsync();
                var categoriasSerializer = new DataContractSerializer(typeof(List<Categoria>));
                foreach (var categoria in categoriasComItens)
                {
                    var nomeArquivo = Path.GetFileName(categoria.ImageUrl);
                    webClient.DownloadFile(categoria.ImageUrl, Path.Combine(CaminhoImagensCategorias, nomeArquivo));
                    categoria.ImageUrl = nomeArquivo;
                    foreach (var item in categoria.Itens)
                    {
                        nomeArquivo = Path.GetFileName(item.ImageUrl);
                        webClient.DownloadFile(item.ImageUrl, Path.Combine(CaminhoImagensItens, nomeArquivo));
                        item.ImageUrl = nomeArquivo;
                    }
                }
                File.Delete(@"Data\categorias.xml");
                using (var fileStream = File.OpenWrite(@"Data\categorias.xml"))
                {
                    categoriasSerializer.WriteObject(fileStream, categoriasComItens);
                    fileStream.Flush();
                }
                Console.WriteLine("Categorias exportadas.");

                Console.WriteLine("Exportando itens...");
                var itensSerializer = new DataContractSerializer(typeof(List<Item>));
                File.Delete(@"Data\itens.xml");
                using (var fileStream = File.OpenWrite(@"Data\itens.xml"))
                {
                    itensSerializer.WriteObject(fileStream, categoriasComItens.SelectMany((c) => c.Itens).ToList());
                    fileStream.Flush();
                }
                Console.WriteLine("Itens exportados.");

                Console.WriteLine("Exportando empresa...");
                var empresa = await CatalogoDataSource.Instance.ObterEmpresaAsync();

                var nomeArquivoImagemEmpresa = Path.GetFileName(empresa.ImageUrl);
                webClient.DownloadFile(empresa.ImageUrl, Path.Combine(CaminhoImagensEmpresa, nomeArquivoImagemEmpresa));
                empresa.ImageUrl = nomeArquivoImagemEmpresa;

                nomeArquivoImagemEmpresa = Path.GetFileName(empresa.LiveTileBig1);
                webClient.DownloadFile(empresa.LiveTileBig1, Path.Combine(CaminhoImagensEmpresa, nomeArquivoImagemEmpresa));
                empresa.LiveTileBig1 = nomeArquivoImagemEmpresa;

                nomeArquivoImagemEmpresa = Path.GetFileName(empresa.LiveTileBig2);
                webClient.DownloadFile(empresa.LiveTileBig2, Path.Combine(CaminhoImagensEmpresa, nomeArquivoImagemEmpresa));
                empresa.LiveTileBig2 = nomeArquivoImagemEmpresa;

                nomeArquivoImagemEmpresa = Path.GetFileName(empresa.LiveTileSmall1);
                webClient.DownloadFile(empresa.LiveTileSmall1, Path.Combine(CaminhoImagensEmpresa, nomeArquivoImagemEmpresa));
                empresa.LiveTileSmall1 = nomeArquivoImagemEmpresa;

                nomeArquivoImagemEmpresa = Path.GetFileName(empresa.LiveTileSmall2);
                webClient.DownloadFile(empresa.LiveTileSmall2, Path.Combine(CaminhoImagensEmpresa, nomeArquivoImagemEmpresa));
                empresa.LiveTileSmall2 = nomeArquivoImagemEmpresa;

                var empresaSerializer = new DataContractSerializer(typeof(Empresa));
                File.Delete(@"Data\empresa.xml");
                using (var fileStream = File.OpenWrite(@"Data\empresa.xml"))
                {
                    empresaSerializer.WriteObject(fileStream, empresa);
                    fileStream.Flush();
                }
                Console.WriteLine("Empresa exportada.");
            }
            catch (Exception e)
            {
                Console.Write("Erro: ");
                Console.WriteLine(e.ToString());
            }
        }

        private static string UploadBlob(CloudBlobContainer container, string pastaBlob, string pastaLocal, string nomeArquivo)
        {
            var blob = container.GetBlockBlobReference(pastaBlob + "/" + nomeArquivo);
            using (var fileStream = File.OpenRead(Path.Combine(pastaLocal, nomeArquivo)))
            {
                blob.UploadFromStream(fileStream);
            }
            return blob.Uri.ToString();
        }
    }
}
